Add route handling for magproto, mapsend, GPX. Thanx, Alex Mottram!
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Tue, 1 Apr 2003 03:21:24 +0000 (03:21 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Tue, 1 Apr 2003 03:21:24 +0000 (03:21 +0000)
gpsbabel/defs.h
gpsbabel/gpx.c
gpsbabel/magellan.h
gpsbabel/magproto.c
gpsbabel/mapsend.c
gpsbabel/reference/route/magellan.rte [new file with mode: 0644]
gpsbabel/reference/route/route.gpx [new file with mode: 0644]
gpsbabel/reference/route/route.mapsend [new file with mode: 0644]
gpsbabel/route.c
gpsbabel/testo
gpsbabel/waypt.c

index f6042da7e2f3c7db33d4e817a4a98a5ac556e8d5..5107b2dc52e3521569d66d5fb28c462d7d353199 100644 (file)
@@ -168,6 +168,7 @@ typedef struct {
        char *rte_name;
        char *rte_desc;
        int rte_num;
+       int rte_waypt_ct;               /* # waypoints in waypoint list */
 } route_head;
 
 typedef void (*ff_init) (char const *, char const *);
@@ -193,6 +194,7 @@ typedef void (*waypt_cb) (const waypoint *);
 typedef void (*route_hdr)(const route_head *);
 typedef void (*route_trl)(const route_head *);
 void waypt_add (waypoint *);
+waypoint * waypt_dupe (waypoint *);
 void waypt_del (waypoint *);
 void waypt_free (waypoint *);
 void waypt_disp_all(waypt_cb);
@@ -208,6 +210,8 @@ void route_disp_all(route_hdr, route_trl, waypt_cb);
 void route_free (route_head *);
 void route_flush( queue *);
 void route_flush_all();
+unsigned int route_waypt_count(void);
+unsigned int route_count(void);
 
 /*
  * All shortname functions take a shortname handle as the first arg.
index e793491249b9727366804b9bb44d3d282bcb55ab..133850d8929e008c85b0cf36eb3e3cf5e6a45b59 100644 (file)
@@ -24,6 +24,7 @@
 
 static int in_wpt;
 static int in_rte;
+static int in_rtept;
 static int in_trk;
 static int in_trkpt;
 static int in_ele;
@@ -66,6 +67,7 @@ static time_t file_time;
 
 static char *gsshortnames = NULL;
 static route_head *trk_head;
+static route_head *rte_head;
 
 #define MYNAME "GPX"
 #define MY_CBUF 4096
@@ -296,8 +298,13 @@ gpx_start(void *data, const char *el, const char **attr)
        else if (strcmp(el, "cmt") == 0) {
                in_cmt++;
        } 
-       else if (strcmp(el, "rtept") == 0) {
+       else if (strcmp(el, "rte") == 0) {
+               rte_head = route_head_alloc();
+               route_add_head(rte_head);
                in_rte++;
+       } 
+       else if (strcmp(el, "rtept") == 0) {
+               in_rtept++;
                tag_wpt(attr);
        } 
        else if (strcmp(el, "trk") == 0) {
@@ -508,6 +515,24 @@ gpx_end(void *data, const char *el)
                if (in_number && in_trk) {
                        trk_head->rte_num = atoi(cdatastr);
                }
+               if (in_name && in_rte && ! in_rtept) {
+                       rte_head->rte_name = xstrdup(cdatastr);
+               }
+               if (in_desc && in_rte && ! in_rtept ) {
+                       rte_head->rte_desc = xstrdup(cdatastr);
+               }
+               if (in_number && in_rte) {
+                       rte_head->rte_num = atoi(cdatastr);
+               }
+               if (in_name && in_rtept) {
+                       wpt_tmp->shortname = xstrdup(cdatastr);
+               }
+               if (in_desc && in_rtept) {
+                       wpt_tmp->notes = xstrdup(cdatastr);
+               }
+               if (in_cmt && in_rtept) {
+                       wpt_tmp->description = xstrdup(cdatastr);
+               }
                if (gsshortnames) {
                        if (in_gs_name && in_wpt && !in_gs_tbugs) {
                                wpt_tmp->notes = xstrdup(cdatastr);
@@ -517,7 +542,7 @@ gpx_end(void *data, const char *el)
                                wpt_tmp->notes = xstrdup(cdatastr);
                        }
                }
-               if (in_cmt && in_wpt) {
+               if ((in_cmt && in_wpt) || (in_cmt && in_rtept)) {
                        wpt_tmp->description = xstrdup(cdatastr);
                }
                if (in_url && in_wpt) {
@@ -526,7 +551,7 @@ gpx_end(void *data, const char *el)
                if (in_urlname && in_wpt) {
                        wpt_tmp->url_link_text = xstrdup(cdatastr);
                }
-               if (in_icon && in_wpt) {
+               if ((in_icon && in_wpt) || (in_icon && in_rtept)) {
                        wpt_tmp->icon_descr = xstrdup(cdatastr);
                        wpt_tmp->icon_descr_is_dynamic = 1;
                }
@@ -535,7 +560,7 @@ gpx_end(void *data, const char *el)
                                &wpt_tmp->position.altitude.altitude_meters);
                }
                if (in_time) {
-                       if ( in_wpt || in_rte || in_trkpt) {
+                       if ( in_wpt || in_rte || in_trkpt || in_rtept) {
                                wpt_tmp->creation_time = 
                                        xml_parse_time( cdatastr );
                        }
@@ -570,10 +595,12 @@ gpx_end(void *data, const char *el)
                waypt_add(wpt_tmp);
                in_wpt--;
                logpoint_ct = 0;
-       }
-       else if (strcmp(el, "rtept") == 0) {
-/*             route_add(wpt_tmp); */
+       } 
+         else if (strcmp(el, "rte") == 0) {
                in_rte--;
+       } else if (strcmp(el, "rtept") == 0) {
+               route_add_wpt(rte_head, wpt_tmp);
+               in_rtept--;
        } else if (strcmp(el, "trk") == 0) {
                in_trk--;
        } else if (strcmp(el, "trkpt") == 0) {
@@ -664,6 +691,11 @@ gpx_cdata(void *dta, const XML_Char *s, int len)
                        (in_trk && in_name) || 
                        (in_trk && in_desc) || 
                        (in_trk && in_number) || 
+                       (in_rte && in_cmt) || 
+                       (in_rte && in_name) || 
+                       (in_rte && in_desc) || 
+                       (in_rte && in_icon) || 
+                       (in_rte && in_number) || 
                        (in_time))  {
                estr = cdatastr + strlen(cdatastr);
                memcpy(estr, s, len);
@@ -965,6 +997,83 @@ void gpx_track_pr()
        route_disp_all(gpx_track_hdr, gpx_track_tlr, gpx_track_disp);
 }
 
+static void
+gpx_route_hdr(const route_head *rte)
+{
+       char * tmp_ent;
+       
+       fprintf(ofd, "<rte>\n");
+       if (rte->rte_name) {
+               tmp_ent = gpx_entitize(rte->rte_name);
+               fprintf(ofd, "<name>%s</name>\n", tmp_ent);
+               xfree(tmp_ent);
+       }
+       if (rte->rte_desc) {
+               tmp_ent = gpx_entitize(rte->rte_desc);
+               fprintf(ofd, "<desc>%s</desc>\n", tmp_ent);
+               xfree(tmp_ent);
+       }
+       if (rte->rte_num) {
+               fprintf(ofd, "<number>%d</number>\n", rte->rte_num);
+       }
+}
+
+static void
+gpx_route_disp(const waypoint *waypointp)
+{
+       fprintf(ofd, "<rtept lat=\"%f\" lon=\"%f\">\n",
+               waypointp->position.latitude.degrees,
+               waypointp->position.longitude.degrees);
+
+       if (waypointp->position.altitude.altitude_meters != unknown_alt) {
+               fprintf(ofd, "<ele>%f</ele>\n",
+                        waypointp->position.altitude.altitude_meters);
+       }
+       if (waypointp->creation_time) {
+               gpx_write_time(waypointp->creation_time,"time");
+       }
+       if (waypointp->shortname) {
+               fprintf(ofd, "<name>");
+               fprintf(ofd, "<![CDATA[%s]]>", waypointp->shortname);
+               fprintf(ofd, "</name>\n");
+       }
+       if (waypointp->description) {
+               fprintf(ofd, "<cmt>");
+               fprintf(ofd, "<![CDATA[%s]]>", waypointp->description);
+               fprintf(ofd, "</cmt>\n");
+       }
+       if (waypointp->notes) {
+               fprintf(ofd, "<desc>");
+               fprintf(ofd, "<![CDATA[%s]]>", waypointp->notes);
+               fprintf(ofd, "</desc>\n");
+       } 
+       if (waypointp->icon_descr) {
+               fprintf(ofd, "<sym>");
+               fprintf(ofd, "<![CDATA[%s]]>", waypointp->icon_descr);
+               fprintf(ofd, "</sym>");
+       }
+
+       fprintf(ofd, "</rtept>\n");
+}
+
+static void
+gpx_route_tlr(const route_head *rte)
+{
+       fprintf(ofd, "</rte>\n");
+}
+
+static
+void gpx_noop()
+{
+}
+
+static
+void gpx_route_pr()
+{
+       /* output routes */
+       route_disp_all(gpx_route_hdr, gpx_route_tlr, gpx_route_disp);
+}
+
 void
 gpx_write(void)
 {
@@ -982,9 +1091,15 @@ gpx_write(void)
 
         gpx_write_time( now, "time" );
        switch(global_opts.objective) {
-               case trkdata: gpx_track_pr(); 
-               case wptdata: waypt_disp_all(gpx_waypt_pr);
-                             break;
+               case trkdata: 
+                               gpx_track_pr();
+                               break;
+               case rtedata: 
+                               gpx_route_pr();
+                               break;
+               case wptdata: 
+                               waypt_disp_all(gpx_waypt_pr);
+                               break;
                default:
                              break;
        }
index 7050befbe1a41cf3bdd5899be08d78cf6ff9cce3..f7a023b16707f63804b75c118259d22e5487bb82 100644 (file)
@@ -48,3 +48,4 @@ const char * mag_find_descr_from_token(const char *token);
 const char * mag_find_token_from_descr(const char *icon);
 
 waypoint * mag_trkparse(char *trkmsg);
+void mag_rteparse(char *rtemsg);
index e9a57e93d13d0826272661157933349f6d46756f..9fe5c3e2eca872fe7b0a96cf80a09d8dc1bfa011 100644 (file)
@@ -67,6 +67,8 @@ typedef struct mag_rte_head {
        int nelems;
 } mag_rte_head;
 
+static queue rte_wpt_tmp; /* temporary PGMNWPL msgs for routes */
+
 static FILE *magfile_in;
 static FILE *magfile_out;
 static int magfd;
@@ -169,7 +171,6 @@ pid_to_model_t pid_to_model[] =
 
 static icon_mapping_t *icon_mapping = map330_icon_table;
 
-
 /*
  *   For each receiver type, return a "cleansed" version of the string
  *   that's valid for a waypoint name or comment.   The string should be
@@ -419,12 +420,25 @@ retry:
        } 
        if (strncmp(ibuf, "$PMGNWPT,", 7) == 0) {
                waypoint *wpt = mag_wptparse(ibuf);
-               waypt_add(wpt);
-       } 
+               switch (global_opts.objective)
+               {
+                       case wptdata:
+                               waypt_add(wpt);
+                               break;
+                       case rtedata:
+                               ENQUEUE_TAIL(&rte_wpt_tmp, &wpt->Q);
+                               break;
+                       default:
+                               break;
+               }
+       }
        if (strncmp(ibuf, "$PMGNTRK,", 7) == 0) {
                waypoint *wpt = mag_trkparse(ibuf);
                route_add_wpt(trk_head, wpt);
-       } 
+       }
+       if (strncmp(ibuf, "$PMGNRTE,", 7) == 0) {
+               mag_rteparse(ibuf);
+       }
        if (IS_TKN("$PMGNVER,")) {
                mag_verparse(ibuf);
        } 
@@ -716,6 +730,8 @@ mag_rd_init(const char *portname, const char *args)
                mag_writemsg("PMGNCMD,NMEAOFF");
        }
 
+       QUEUE_INIT(&rte_wpt_tmp);
+
        return;
 }
 
@@ -760,6 +776,7 @@ mag_wr_init(const char *portname, const char *args)
 #endif
                mag_rd_init(portname, args);
        }
+       QUEUE_INIT(&rte_wpt_tmp);
 }
 
 static void
@@ -773,6 +790,8 @@ mag_deinit(void)
        if(mkshort_handle)
                mkshort_del_handle(mkshort_handle);
        mkshort_handle = NULL;
+
+       waypt_flush(&rte_wpt_tmp);
 }
 
 
@@ -834,7 +853,7 @@ mag_trkparse(char *trkmsg)
  * $PMGNRTE,4,1,c,1,DAD,a,Anna,a*61
  * generate a route.
  */
-waypoint * 
+void
 mag_rteparse(char *rtemsg)
 {
        char descr[100];
@@ -844,7 +863,8 @@ mag_rteparse(char *rtemsg)
        char *currtemsg;
        static mag_rte_head *mag_rte_head;
        mag_rte_elem *rte_elem;
-
+       char *p;
+       
        descr[0] = 0;
 
        sscanf(rtemsg,"$PMGNRTE,%d,%d,%c,%d%n", 
@@ -852,9 +872,7 @@ mag_rteparse(char *rtemsg)
 
        /*
         * This is the first component of a route.  Allocate a new
-        * queue head.   It's kind of unfortunate that we can't know
-        * a priori how many items are on this track, so we have to
-        * alloc and chain those as we go.
+        * queue head.   
         */
        if (frag == 1) {
                mag_rte_head = xcalloc(sizeof (*mag_rte_head),1);
@@ -869,13 +887,20 @@ mag_rteparse(char *rtemsg)
         * loop and pick those up.
         */
        while (sscanf(currtemsg,",%[^,],%[^,]%n",next_stop, abuf,&n)) {
-               if (next_stop[0] == 0) {
+               if ((next_stop[0] == 0) || (next_stop[0] == '*')) {
                        break;
                }
+               
+               /* trim CRC from waypoint icon string */
+               if ((p = strchr(abuf, '*')) != NULL)
+                       *p = '\0';
+
                rte_elem = xcalloc(sizeof (*rte_elem),1);
                QUEUE_INIT(&rte_elem->Q);
+
                rte_elem->wpt_name = xstrdup(next_stop);
                rte_elem->wpt_icon = xstrdup(abuf);
+
                ENQUEUE_TAIL(&mag_rte_head->Q, &rte_elem->Q);
                next_stop[0] = 0;
                currtemsg += n;
@@ -891,28 +916,38 @@ mag_rteparse(char *rtemsg)
 
                rte_head = route_head_alloc();
                route_add_head(rte_head);
+               rte_head->rte_num = rtenum;
 
-               /*
-                *  TODO: I suppose we have to fetch the waypoints to
-                *  get the underlying data for each stop in the route.
+               /* 
+                * It is quite feasible that we have 200 waypoints,
+                * 3 of which are used in the route.  We'll need to find
+                * those in the queue for SD routes...
                 */
+
                QUEUE_FOR_EACH(&mag_rte_head->Q, elem, tmp) {
-                       static int lat; /* Dummy data */
                        mag_rte_elem *re = (mag_rte_elem *) elem;
                        waypoint *waypt;
+                       queue *welem, *wtmp;
 
-                       waypt  = xcalloc(sizeof *waypt, 1);
-
-                       /* TODO Populate rest of waypoint. */
-                       waypt->shortname = re->wpt_name;
-                       waypt->position.latitude.degrees = ++lat;
+                       /* 
+                        * Copy route points from temp wpt queue. 
+                        */
+                       QUEUE_FOR_EACH(&rte_wpt_tmp, welem, wtmp) {
+                               waypt = (waypoint *)welem;
+                               if (strcmp(waypt->shortname, re->wpt_name) == 0) {
+                                       waypoint * wpt = waypt_dupe(waypt);
+                                       route_add_wpt(rte_head, wpt);
+                                       break;
+                               }
+                       }
 
-                       route_add_wpt(rte_head, waypt);
                        dequeue(&re->Q);
+                       xfree(re->wpt_name);
+                       xfree(re->wpt_icon);
                        xfree(re);
                }
+               xfree(mag_rte_head);
        }
-       return 0;
 }
 
 const char *
@@ -1003,7 +1038,8 @@ mag_wptparse(char *trkmsg)
        
        for (blah = icons ; blah < icone; blah++)
                icon_token[i++] = *blah;
-
+       icon_token[i++] = '\0';
+       
        if (latdir == 'S') latdeg = -latdeg;
        waypt->position.latitude.degrees = mag2degrees(latdeg);
 
@@ -1021,6 +1057,8 @@ mag_wptparse(char *trkmsg)
 static void
 mag_read(void)
 {
+       found_done = 0;
+
        switch (global_opts.objective)
        {
                case trkdata:
@@ -1030,17 +1068,51 @@ mag_read(void)
                        if (!is_file) 
                                mag_writemsg("PMGNCMD,TRACK,2");
 
+                       while (!found_done) {
+                               mag_readmsg();
+                       }
+
                        break;
                case wptdata:
                        if (!is_file) 
                                mag_writemsg("PMGNCMD,WAYPOINT");
+
+                       while (!found_done) {
+                               mag_readmsg();
+                       }
+
                        break;
-               default:
-                       fatal(MYNAME ": Routes are not yet supported\n");
-       }
+               case rtedata:
+                       if (!is_file) {
+                               /* 
+                                * serial routes require waypoint & routes 
+                                * messages commands.
+                                */
+                               mag_writemsg("PMGNCMD,WAYPOINT");
 
-       while (!found_done) {
-               mag_readmsg();
+                               while (!found_done) {
+                                       mag_readmsg();
+                               }
+
+                               mag_writemsg("PMGNCMD,ROUTE");
+
+                               found_done = 0;
+                               while (!found_done) {
+                                       mag_readmsg();
+                               }
+                       } else {
+                               /*
+                                * SD routes are a stream of PMGNWPL and 
+                                * PMGNRTE messages, in that order.
+                                */
+                               while (!found_done) {
+                                       mag_readmsg();
+                               }
+                       }
+
+                       break;
+               default:
+                       fatal(MYNAME ": Unknown objective\n");
        }
 }
 
@@ -1169,6 +1241,80 @@ void mag_track_pr()
        route_disp_all(mag_track_nop, mag_track_nop, mag_track_disp);
 }
 
+/*
+The spec says to stack points:
+       $PMGNRTE,2,1,c,1,FOO,POINT1,b,POINT2,c,POINT3,d*6C<CR><LF>
+
+Meridian SD card and serial (at least) writes in pairs:
+       $PMGNRTE,4,1,c,1,HOME,c,I49X73,a*15
+       ...
+       $PMGNRTE,4,4,c,1,RON273,a,MYCF93,a*7B
+       
+The spec also says that some units don't like single-legged pairs,
+and to replace the 2nd name with "<<>>", but I haven't seen one of those.
+*/
+
+static void
+mag_route_trl(const route_head * rte)
+{
+       queue *elem, *tmp;
+       waypoint *waypointp;
+       char obuff[256];
+       char buff1[64], buff2[64];
+       char *pbuff;
+       const char * icon_token;
+       int i, numlines, thisline;
+       
+       /* count waypoints for this route */
+       i = rte->rte_waypt_ct;
+
+       /* number of output PMGNRTE messages at 2 points per line */
+       numlines = (i / 2) + (i % 2);
+       
+       thisline = i = 0;
+       QUEUE_FOR_EACH(&rte->waypoint_list, elem, tmp) {
+               waypointp = (waypoint *) elem;
+               i++;
+
+               if (deficon)
+                       icon_token = mag_find_token_from_descr(deficon);
+               else
+                       icon_token = mag_find_token_from_descr(waypointp->icon_descr);
+                       
+               if (i == 1)
+                       pbuff = buff1;
+               else
+                       pbuff = buff2;
+
+               sprintf(pbuff, "%s,%s", waypointp->shortname, icon_token);
+               
+               if ((tmp == &rte->waypoint_list) || ((i % 2) == 0)) {
+                       thisline++;
+                       
+                       sprintf(obuff, "PMGNRTE,%d,%d,c,%d,%s,%s", 
+                               numlines, thisline, rte->rte_num,
+                               buff1, buff2);
+
+                       mag_writemsg(obuff);
+                       buff1[0] = '\0';
+                       buff2[0] = '\0';
+                       i = 0;
+               }
+       }
+}
+
+static void
+mag_route_hdr()
+{
+}
+
+static void
+mag_route_pr()
+{
+       route_disp_all(mag_route_hdr, mag_route_trl, mag_waypt_pr);
+
+}
+
 static void
 mag_write(void)
 {
@@ -1185,8 +1331,11 @@ mag_write(void)
                case wptdata:
                        waypt_disp_all(mag_waypt_pr);
                        break;
+               case rtedata:
+                       mag_route_pr();
+                       break;
                default:
-                       fatal(MYNAME ": Routes are not yet supported\n");
+                       fatal(MYNAME ": Unknown objective.\n");
        }
 }
 
index 78af2c006c3ec4939def996cc3072b9d84a51a36..dcd16f85524d2e1ea877df4e8663c84c589bb9c5 100644 (file)
@@ -32,6 +32,8 @@ static void *mkshort_handle;
 static int endianness_tested;
 static int i_am_little_endian;
 
+static int route_wp_count;
+
 #define MYNAME "mapsend"
 
 static void
@@ -174,6 +176,7 @@ mapsend_wr_init(const char *fname, const char *args)
                exit(1);
        }
        mkshort_handle = mkshort_new_handle();
+       route_wp_count = 0;
 }
 
 static void
@@ -190,7 +193,7 @@ mapsend_wpt_read(void)
        char name[257];
        char comment[257];
        char *p;
-       int wpt_count;
+       int wpt_count, rte_count, rte_num;
        unsigned char scount;
        int wpt_number;
        char wpt_icon;
@@ -199,8 +202,10 @@ mapsend_wpt_read(void)
        double wpt_long;
        double wpt_lat;
        waypoint *wpt_tmp;
-       my_fread4(&wpt_count, mapsend_file_in);
+       route_head *rte_head;
 
+       my_fread4(&wpt_count, mapsend_file_in);
+       
        while (wpt_count--) {
                wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1);
 
@@ -238,6 +243,55 @@ mapsend_wpt_read(void)
 
                waypt_add(wpt_tmp);
        }
+       
+       /* now read the routes... */
+       my_fread4(&rte_count, mapsend_file_in);
+       
+       while (rte_count--) {
+               rte_head = route_head_alloc();
+               route_add_head(rte_head);
+               
+               /* route name */
+               fread(&scount, sizeof(scount), 1, mapsend_file_in);
+               fread(tbuf, scount, 1, mapsend_file_in);
+               tbuf[scount] = '\0';
+               rte_head->rte_name = xstrdup(tbuf);
+               
+               /* route # */
+               my_fread4(&rte_num, mapsend_file_in);
+               rte_head->rte_num = rte_num;
+               
+               /* points this route */
+               my_fread4(&wpt_count, mapsend_file_in);
+               
+               while (wpt_count--) {
+                       wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1);
+
+                       /* waypoint name */
+                       fread(&scount, sizeof(scount), 1, mapsend_file_in);
+                       fread(tbuf, scount, 1, mapsend_file_in);
+                       tbuf[scount] = '\0';
+
+                       wpt_tmp->shortname = xstrdup(tbuf);
+                       
+                       /* waypoint # */
+                       my_fread4(&wpt_number, mapsend_file_in);
+                       my_fread8(&wpt_long, mapsend_file_in);
+                       my_fread8(&wpt_lat, mapsend_file_in);
+                       fread(&wpt_icon, sizeof(wpt_icon), 1, mapsend_file_in);
+
+                       wpt_tmp->position.longitude.degrees = wpt_long;
+                       wpt_tmp->position.latitude.degrees = -wpt_lat;
+
+                       if (wpt_icon < 26)
+                               sprintf(tbuf, "%c", wpt_icon + 'a');
+                       else
+                               sprintf(tbuf, "a%c", wpt_icon - 26 + 'a');
+                       wpt_tmp->icon_descr = mag_find_descr_from_token(tbuf);
+
+                       route_add_wpt(rte_head, wpt_tmp);
+               }
+       }
 }
 
 static void
@@ -354,6 +408,7 @@ n = ++cnt;
        }
        fwrite(&n, 1, 1, mapsend_file_out);
 n = 1;
+               
        fwrite(&n, 1, 1, mapsend_file_out);
 
        falt = waypointp->position.altitude.altitude_meters;
@@ -365,20 +420,108 @@ n = 1;
        my_fwrite8(&flat, mapsend_file_out);
 }
 
-void
+static void 
+mapsend_route_hdr(const route_head *rte)
+{
+       int wp_ct;
+       unsigned char c;
+       char * rname;
+       
+       /* route name -- mapsend really seems to want something here.. */
+       if (!rte->rte_name)
+               rname = xstrdup("Route");
+       else
+               rname = xstrdup(rte->rte_name);
+
+       c = strlen(rname);
+       
+       fwrite(&c, 1, 1, mapsend_file_out);
+       fwrite(rname, c, 1, mapsend_file_out);
+
+       xfree(rname);
+       
+       /* route # */
+       c = rte->rte_num;
+       my_fwrite4(&c, mapsend_file_out);
+       
+       wp_ct = rte->rte_waypt_ct;
+
+       /* # of waypoints to follow... */
+       my_fwrite4(&wp_ct, mapsend_file_out);
+}
+
+static void 
+mapsend_noop()
+{
+       /* no-op */
+}
+
+static void 
+mapsend_route_disp(const waypoint *waypointp)
+{
+       unsigned char c;
+       const char *iconp;
+       double dbl;
+       int n;
+
+       route_wp_count++;
+       
+       /* waypoint name */
+       c = strlen(waypointp->shortname);
+       fwrite(&c, 1, 1, mapsend_file_out);
+       fwrite(waypointp->shortname, c, 1, mapsend_file_out);
+       
+       /* waypoint number */
+       my_fwrite4(&route_wp_count, mapsend_file_out);
+
+       dbl = waypointp->position.longitude.degrees;
+       my_fwrite8(&dbl, mapsend_file_out);
+
+       dbl = -waypointp->position.latitude.degrees;
+       my_fwrite8(&dbl, mapsend_file_out);
+
+       if (waypointp->icon_descr) {
+               iconp = mag_find_token_from_descr(waypointp->icon_descr);
+               if (1 == strlen(iconp)) {
+                       n = iconp[0] - 'a';
+               } else {
+                       n = iconp[1] - 'a' + 26;
+               }
+       } else  {
+               n = 0;
+       }
+       fwrite(&n, 1, 1, mapsend_file_out);
+}
+
+static void
 mapsend_wpt_write(void)
 {
        mapsend_hdr hdr = {13, "4D533330 MS", "30", ms_type_wpt, 0};
        int wpt_count = waypt_count();
        int n = 0;
-
+       
        fwrite(&hdr, sizeof(hdr), 1, mapsend_file_out);
-       my_fwrite4(&wpt_count, mapsend_file_out);
 
-       waypt_disp_all(mapsend_waypt_pr);
+       if (global_opts.objective == wptdata) {
+               my_fwrite4(&wpt_count, mapsend_file_out);
+               waypt_disp_all(mapsend_waypt_pr);
+       } else 
+       if (global_opts.objective == rtedata) {
+
+               /* # of points - all routes */
+               n = route_waypt_count();
+               my_fwrite4(&n, mapsend_file_out);
+
+               /* write points - all routes */
+               route_disp_all(mapsend_noop, mapsend_noop, mapsend_waypt_pr);
+       }
+               
+       n = route_count();
 
        my_fwrite4(&n, mapsend_file_out);
-/* TODO: Implement routes here */
+       
+       if (n)
+               route_disp_all(mapsend_route_hdr, mapsend_noop, mapsend_route_disp);
 }
 
 #if LATER
diff --git a/gpsbabel/reference/route/magellan.rte b/gpsbabel/reference/route/magellan.rte
new file mode 100644 (file)
index 0000000..d7b9b55
--- /dev/null
@@ -0,0 +1,22 @@
+$PMGNWPL,3042.000,N,09224.000,W,0000000,M,49B,,a*01\r
+$PMGNWPL,3012.000,N,09218.000,W,0000000,M,49A,,a*08\r
+$PMGNWPL,2924.000,N,09212.000,W,0000000,M,48B,,a*0D\r
+$PMGNWPL,2900.000,N,09154.000,W,0000000,M,48A,,a*09\r
+$PMGNWPL,2824.000,N,09124.000,W,0000000,M,47B,,a*05\r
+$PMGNWPL,2748.000,N,09106.000,W,0000000,M,47A,,a*03\r
+$PMGNWPL,2636.000,N,09018.000,W,0000000,M,46A,,a*04\r
+$PMGNWPL,2424.000,N,08824.000,W,0000000,M,43A,,a*06\r
+$PMGNWPL,2336.000,N,08712.000,W,0000000,M,42A,,a*09\r
+$PMGNWPL,2300.000,N,08536.000,W,0000000,M,41A,,a*0B\r
+$PMGNWPL,2218.000,N,08424.000,W,0000000,M,40A,,a*00\r
+$PMGNRTE,6,1,c,0,49B,a,49A,a*00\r
+$PMGNRTE,6,2,c,0,48B,a,48A,a*03\r
+$PMGNRTE,6,3,c,0,47B,a,47A,a*02\r
+$PMGNRTE,6,4,c,0,46A,a,43A,a*03\r
+$PMGNRTE,6,5,c,0,42A,a,41A,a*04\r
+$PMGNRTE,6,6,c,0,40A,a,*0C\r
+$PMGNWPL,3016.831,N,09141.153,W,0000000,M,ATLAUN,Launch at Butte LaRose,i*15\r
+$PMGNWPL,3017.463,N,09137.630,W,0000000,M,ATWRNC,Canal to Warner Lake,k*38\r
+$PMGNWPL,3018.883,N,09138.767,W,0000000,M,ATWRNR,Warner Lake,a*78\r
+$PMGNRTE,2,1,c,1,ATLAUN,i,ATWRNC,k*1A\r
+$PMGNRTE,2,2,c,1,ATWRNR,a,*44\r
diff --git a/gpsbabel/reference/route/route.gpx b/gpsbabel/reference/route/route.gpx
new file mode 100644 (file)
index 0000000..b8d58a1
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<gpx
+ version="1.0"
+creator="GPSBabel - http://gpsbabel.sourceforge.net"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xmlns="http://www.topografix.com/GPX/1/0"
+xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
+<time>2003-03-31T16:25:59Z</time>
+<rte>
+<name>LILI PATH</name>
+<desc>Hurricane LILI</desc>
+<rtept lat="30.700000" lon="-92.400000">
+<ele>0.000000</ele>
+<name><![CDATA[49B]]></name>
+<sym><![CDATA[crossed square]]></sym></rtept>
+<rtept lat="30.200000" lon="-92.300000">
+<ele>0.000000</ele>
+<name><![CDATA[49A]]></name>
+<sym><![CDATA[crossed square]]></sym></rtept>
+<rtept lat="29.400000" lon="-92.200000">
+<ele>0.000000</ele>
+<name><![CDATA[48B]]></name>
+<sym><![CDATA[crossed square]]></sym></rtept>
+<rtept lat="29.000000" lon="-91.900000">
+<ele>0.000000</ele>
+<name><![CDATA[48A]]></name>
+<sym><![CDATA[crossed square]]></sym></rtept>
+<rtept lat="28.400000" lon="-91.400000">
+<ele>0.000000</ele>
+<name><![CDATA[47B]]></name>
+<sym><![CDATA[crossed square]]></sym></rtept>
+<rtept lat="27.800000" lon="-91.100000">
+<ele>0.000000</ele>
+<name><![CDATA[47A]]></name>
+<sym><![CDATA[crossed square]]></sym></rtept>
+<rtept lat="26.600000" lon="-90.300000">
+<ele>0.000000</ele>
+<name><![CDATA[46A]]></name>
+<sym><![CDATA[crossed square]]></sym></rtept>
+<rtept lat="24.400000" lon="-88.400000">
+<ele>0.000000</ele>
+<name><![CDATA[43A]]></name>
+<sym><![CDATA[crossed square]]></sym></rtept>
+<rtept lat="23.600000" lon="-87.200000">
+<ele>0.000000</ele>
+<name><![CDATA[42A]]></name>
+<sym><![CDATA[crossed square]]></sym></rtept>
+<rtept lat="23.000000" lon="-85.600000">
+<ele>0.000000</ele>
+<name><![CDATA[41A]]></name>
+<sym><![CDATA[crossed square]]></sym></rtept>
+<rtept lat="22.300000" lon="-84.400000">
+<ele>0.000000</ele>
+<name><![CDATA[40A]]></name>
+<sym><![CDATA[crossed square]]></sym></rtept>
+</rte>
+<rte>
+<name>ATCHAFALAYA</name>
+<desc>ROUTE1</desc>
+<number>1</number>
+<rtept lat="30.280517" lon="-91.685883">
+<ele>0.000000</ele>
+<name><![CDATA[ATLAUN]]></name>
+<desc><![CDATA[Launch at Butte LaRose]]></desc>
+<sym><![CDATA[Boating]]></sym></rtept>
+<rtept lat="30.291050" lon="-91.627167">
+<ele>0.000000</ele>
+<name><![CDATA[ATWRNC]]></name>
+<desc><![CDATA[Canal to Warner Lake]]></desc>
+<sym><![CDATA[Exit Ramp]]></sym></rtept>
+<rtept lat="30.314717" lon="-91.646117">
+<ele>0.000000</ele>
+<name><![CDATA[ATWRNR]]></name>
+<desc><![CDATA[Warner Lake]]></desc>
+<sym><![CDATA[Hunt/Fish]]></sym></rtept>
+</rte>
+</gpx>
diff --git a/gpsbabel/reference/route/route.mapsend b/gpsbabel/reference/route/route.mapsend
new file mode 100644 (file)
index 0000000..2fd785e
Binary files /dev/null and b/gpsbabel/reference/route/route.mapsend differ
index 09f332d05c7b090a6b1b0e4065fe6bad9b59a12e..9eeff49a90bc21f1ce27e3450ca6338481e52758 100644 (file)
@@ -21,6 +21,8 @@
 #include "defs.h"
 
 static queue my_route_head;
+static int rte_head_ct;
+static int rte_waypts;
 
 void
 route_init(void)
@@ -28,6 +30,18 @@ route_init(void)
        QUEUE_INIT(&my_route_head);
 }
 
+unsigned int
+route_waypt_count(void)
+{
+       /* total wapoint count -- all routes */
+       return rte_waypts;
+}
+
+unsigned int
+route_count(void)
+{
+       return rte_head_ct;     /* total # of routes */
+}
 
 route_head *
 route_head_alloc(void)
@@ -44,12 +58,15 @@ route_add_head(route_head *rte)
 {
        ENQUEUE_TAIL(&my_route_head, &rte->Q);
        QUEUE_INIT(&rte->waypoint_list);
+       rte_head_ct++;
 }
 
 void
 route_add_wpt(route_head *rte, waypoint *wpt)
 {
        ENQUEUE_TAIL(&rte->waypoint_list, &wpt->Q);
+       rte->rte_waypt_ct++;    /* waypoints in this route */
+       rte_waypts++;           /* total waypoints in all routes */
 }
 
 void
index 752a33d9c3c715b5f529365485f6adcc8d68abc0..624032c38204861c20e3a88356a3a91852d804d4 100755 (executable)
@@ -238,3 +238,30 @@ ${PNAME} -i geo -f geocaching.loc -o csv -F ${TMPDIR}/filterpos.csv1
 ${PNAME} -i geo -f geocaching.loc -f geocaching.loc -x position,distance=5f \
                -o csv -F ${TMPDIR}/filterpos.csv2
 compare ${TMPDIR}/filterpos.csv1 ${TMPDIR}/filterpos.csv2
+
+#
+# magellan SD card waypoint / route format
+#
+rm -f ${TMPDIR}/magellan.rte
+${PNAME} -r -i magellan -f reference/route/magellan.rte -o magellan \
+         -F ${TMPDIR}/magellan.rte
+compare ${TMPDIR}/magellan.rte reference/route/magellan.rte
+
+#
+# GPX routes -- since GPX contains a date stamp, tests will always
+# fail, so we use magellan as an interim format...
+#
+rm -f ${TMPDIR}/gpxroute.gpx ${TMPDIR}/maggpx.rte
+${PNAME} -r -i gpx -f reference/route/route.gpx -o gpx \
+         -F ${TMPDIR}/gpxroute.gpx
+${PNAME} -r -i gpx -f ${TMPDIR}/gpxroute.gpx -o magellan \
+         -F ${TMPDIR}/maggpx.rte
+compare ${TMPDIR}/maggpx.rte reference/route/magellan.rte
+
+#
+# MAPSEND waypoint / route format
+#
+rm -f ${TMPDIR}/route.mapsend
+${PNAME} -r -i mapsend -f reference/route/route.mapsend -o mapsend \
+         -F ${TMPDIR}/route.mapsend
+compare ${TMPDIR}/route.mapsend reference/route/
index 2ca9c6badf78c434476c4c9f540ed9740bb7840e..9a5db5e7452e123620c1f8c027934837a2c67235 100644 (file)
@@ -33,6 +33,26 @@ waypt_init(void)
        QUEUE_INIT(&waypt_head);
 }
 
+waypoint *
+waypt_dupe(waypoint *wpt) 
+{
+       waypoint * tmp;
+       tmp = xcalloc(sizeof *wpt, 1);
+       memcpy(tmp, wpt, sizeof(waypoint));
+
+       if (wpt->shortname)
+               tmp->shortname = xstrdup(wpt->shortname);
+       if (wpt->description)
+               tmp->description = xstrdup(wpt->description);
+       if (wpt->notes)
+               tmp->notes = xstrdup(wpt->notes);
+       if (wpt->url)
+               tmp->url = xstrdup(wpt->url);
+       if (wpt->url_link_text)
+               tmp->url_link_text = xstrdup(wpt->url_link_text);
+
+       return tmp;
+}
 void
 waypt_add(waypoint *wpt)
 {